/******************************************************************
Copyright © LibKz 2017~2023. All rights reserved.
* @projectName   LibKz
* @author        Raiiwhen
* @email         masterraii@icloud.com
*******************************************************************/

#include "io_human.h"

void IoHumanLedInit(ioHumanLed* led, stdIO ctrlHandle, ioHumanLedState defaultState)
{
    if (led == NULL || ctrlHandle == NULL) {
        return;
    }
    led->ctrlSetBrightness = NULL; // no brightness control by default
    led->ctrlHandle = ctrlHandle;
    led->ctrlHandle(GPIO_SET);
    led->idleState = defaultState;
    led->state = defaultState;
    led->exeFreq = 100;
    led->timeCnt = 0;
    led->timeStep = 1000 / led->exeFreq;
    led->timePeriod =  1000;
}

void IoHumanLedConfigPWM(ioHumanLed* led, stdSetVal ctrlSetBrightness)
{
    led->ctrlSetBrightness = ctrlSetBrightness;
}

static void IoHumanLedBreath(ioHumanLed* led)
{
    if (led == NULL || led->ctrlSetBrightness == NULL) {
        led->ctrlHandle(GPIO_CLR);
    }
    // breath by Saw Function
    // two saw curve in one period
    if (led->timeCnt > led->timePeriod / 2) {
        led->timeCnt = led->timePeriod;
    }
    float val = (float)led->timeCnt / ((float)led->timePeriod / 2.0f);
    if (led->timeCnt > led->timePeriod / 4) val = 1.0f - val;
    led->ctrlSetBrightness(val);
}

static void IoHumanLedBlink(ioHumanLed* led)
{
    int time = 250; // blink every 250ms
    if ((led->timeCnt % time) > (time / 2)) {
        led->ctrlHandle(GPIO_SET);
    } else {
        led->ctrlHandle(GPIO_CLR);
    }
}

void IoHumanLedExe(ioHumanLed* led)
{
    led->timeCnt += led->timeStep;
    if (led->timeCnt >= led->timePeriod) {
        led->timeCnt = 0;
    }
    switch (led->state)
    {
    case IO_HUMAN_LED_BREATH:
        IoHumanLedBreath(led);
        break;
    
    case IO_HUMAN_LED_BLINK:
        IoHumanLedBlink(led);

    default:
        IoHumanLedBlink(led);
    }
}

void IoHumanLedPushEvent(ioHumanLedState idleState)
{

}